home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / uusrc.arc / UUDECODE.C < prev    next >
C/C++ Source or Header  |  1987-02-16  |  6KB  |  274 lines

  1. /*
  2.  * Uudecode -- decode a uuencoded file back to binary form.
  3.  *
  4.  * modified for Lattice C on the ST - 11.05.86 by MSD
  5.  * modified for Alcyon on the ST -    10-24-86 by RDR
  6.  * modified (a lot) for MWC on the ST 02/07/87 by JPHD 
  7.  * (Some more to be done on the I/O speed...)
  8.  *
  9.  */
  10.  
  11. #include <stdio.h>
  12. #include <osbind.h>
  13.  
  14. extern FILE *fopen();
  15. extern char *strcpy();
  16.  
  17. char *getnword();
  18.  
  19. #define MAXCHAR 127
  20. #define LINELEN 80
  21. #define FILELEN 64
  22. #define CODEDLN 61
  23. #define NORMLEN 45
  24.  
  25. char *mism = "Part suffix mismatch: <%> instead of <%>.\r\n";
  26. #define SUBS1     23
  27. #define SUBS2    38
  28.  
  29. FILE  *in, *out;
  30. char ifname[FILELEN];
  31. char chtbl[MAXCHAR];
  32. char *pos;
  33. char blank, part = '\0';
  34. int partn = 'a';
  35. int lens;
  36.  
  37. main(argc, argv) int argc; char *argv[];
  38. {
  39.     register int i, j;
  40.     char dest[FILELEN], buf[LINELEN];
  41.  
  42.     if (argc < 2) {
  43.         Console("Almost foolproof uudecode v1.0 15-Feb-1987 JPHD\r\n");
  44.         Console("Usage: uudecode inputfile\r\n");
  45.         exit(1);
  46.     }
  47.         if((in = fopen(argv[1], "r")) == NULL) {
  48.         Console("Cant open input file.\r\n");
  49.         exit(2);
  50.     }
  51.  
  52. /*
  53.  * Set up the default translation table. 
  54.  */
  55.     for (i = 0; i < ' '; i++) chtbl[i] = '\0';
  56.     for (i = ' ', j = 0; i < ' ' + 64; i++, j++) chtbl[i] = j;
  57.     for (i = ' ' + 64; i < MAXCHAR; i++) chtbl[i] = '\0';
  58.     chtbl['`'] = chtbl[' '];    /* common mutation */
  59.     chtbl['~'] = chtbl['^'];    /* an other common mutation */
  60.     blank = ' ';
  61. /*
  62.  * search for header or translation table line.
  63.  */
  64.     for (;;) {
  65.         if (fgets(buf, sizeof buf, in) == NULL) {
  66.             Console("No begin line\r\n");
  67.             exit(3);
  68.         }
  69.         if (strncmp(buf, "table", 5) == 0) {
  70.             gettable();
  71.             continue;
  72.         }
  73.         if (strncmp(buf, "begin", 5) == 0) {
  74.             break;
  75.         }
  76.     }
  77.     lens = strlen(buf);
  78.     if (lens) buf[--lens] = '\0';
  79.     if ((pos = getnword(buf, 3)) == NULL) {
  80.         Console("Missing filename in begin line.\r\n");
  81.         exit(10);
  82.     } else
  83.         strcpy(dest, pos);
  84.  
  85.     if((out = fopen(dest, "wb")) == NULL) {
  86.         Console("Cannot open output file\r\n");
  87.         exit(4);
  88.     }
  89.     decode();
  90.     fclose(out);
  91.     exit(0);
  92. }
  93. /*
  94.  * Bring back a pointer to the start of the nth word.
  95.  */
  96. char *getnword(str, n) register char *str; register int n;
  97. {
  98.     while((*str == '\t') || (*str == ' ')) str++;
  99.     if (! *str) return NULL;
  100.     while(--n) {
  101.         while ((*str != '\t') && (*str != ' ') && (*str)) str++;
  102.         if (! *str) return NULL;
  103.         while((*str == '\t') || (*str == ' ')) str++;
  104.         if (! *str) return NULL;
  105.     }
  106.     return str;
  107. }
  108.  
  109. /*
  110.  * Install the table in memory for later use.
  111.  */
  112. gettable()
  113. {
  114.     char buf[LINELEN];
  115.     register int c, n = 0;
  116.     register char *cpt;
  117.  
  118.     for (c = 0; c <= MAXCHAR; c++) chtbl[c] = '\0';
  119.  
  120. again:    if (fgets(buf, sizeof buf, in) == NULL) {
  121.         Console("EOF while in translation table.\r\n");
  122.         exit(5);
  123.     }
  124.     if (strncmp(buf, "begin", 5) == 0) {
  125.         Console("Incomplete translation table.\r\n");
  126.         exit(6);
  127.     }
  128.     cpt = buf + strlen(buf) - 1;
  129.     *cpt = ' ';
  130.     while (*(cpt) == ' ') {
  131.         *cpt = '\0'; 
  132.         cpt--;
  133.     }
  134.     cpt = buf;
  135.     while (c = *cpt) {
  136.         if (chtbl[c] != '\0') {
  137.             Console("Duplicate char in translation table.\n");
  138.             exit(6);
  139.         }
  140.         if (n == 0) blank = c;
  141.         chtbl[c] = n++;
  142.         if (n >= 64) return;
  143.         cpt++;
  144.     }
  145.     goto again;
  146. }
  147.  
  148. /*
  149.  * copy from in to out, decoding as you go along.
  150.  */
  151.  
  152. decode()
  153. {
  154.     char buf[LINELEN], outl[LINELEN];
  155.     register char *bp, *ut, *trtbl = chtbl;
  156.     register unsigned int n, c, len;
  157.  
  158.     for (;;) {
  159.         if (fgets(buf, sizeof buf, in) == NULL) {
  160.             Console("Short file.\r\n");
  161.             return;
  162.         }
  163.         len = strlen(buf);
  164.         if (len) buf[--len] = '\0';
  165. /*
  166.  * Get the binary line length.
  167.  */
  168.         n = trtbl[*buf];
  169.         if (n == NORMLEN) goto decod;
  170. /*
  171.  * end of uuencoded file ?
  172.  */
  173.         if (strncmp(buf, "end", 3) == 0) return;
  174. /*
  175.  * end of current file ? : get next one.
  176.  */
  177.         if (strncmp(buf, "include", 7) == 0) {
  178.             getfile(buf);
  179.             continue;
  180.         }
  181. /*
  182.  * Is it the empty line before the end line ?
  183.  */
  184.         if (n <= 0) continue;
  185. /*
  186.  * Pad with blanks.
  187.  */
  188. decod:        for (bp = &buf[c = len];
  189.              c < CODEDLN; c++, bp++) *bp = blank;
  190.  
  191. /*
  192.  * output a group of 3 bytes (4 input characters).
  193.  * the input chars are pointed to by p, they are to
  194.  * be output to file f.  n is used to tell us not to
  195.  * output all of them at the end of the file.
  196.  */
  197.         ut = outl;
  198.         len = n;
  199.         bp = &buf[1];
  200.         while (n > 0) {
  201.             *(ut++) = trtbl[*bp] << 2 | trtbl[bp[1]] >> 4;
  202.             n--;
  203.             if (n) {
  204.                 *(ut++) = trtbl[bp[1]] << 4 | trtbl[bp[2]] >> 2;
  205.                 n--;
  206.             }
  207.             if (n) {
  208.                 *(ut++) = trtbl[bp[2]] << 6 | trtbl[bp[3]];
  209.                 n--;
  210.             }
  211.             bp += 4;
  212.         }
  213.         n = fwrite(outl, 1, len, out);
  214.     }
  215. }
  216.  
  217. /* you may need to rename the filenames at the ends of each part
  218. * if the encoder encoded them on directories and specified drives.
  219. */
  220. getfile(buf) register char *buf;
  221. {
  222.     if ((pos = getnword(buf, 2)) == NULL) {
  223.         Console("Missing include file name.\r\n");
  224.         exit(11);
  225.     } else
  226.         strcpy(ifname, pos);
  227.  
  228.     if (freopen(ifname, "r", in) != in) {
  229.         Console("Cannot reassign input file to included file.\r\n");
  230.         exit(7);
  231.     }
  232.     for (;;) {
  233.         if (fgets(buf, LINELEN, in) == NULL) {
  234.             Console("No begin line in included file: ");
  235.             Console(ifname);
  236.             Console(".\r\n");
  237.             exit(3);
  238.         }
  239.  
  240.         if (strncmp(buf, "table", 5) == 0) {
  241.             gettable();
  242.             continue;
  243.         }
  244.         if (strncmp(buf, "begin", 5) == 0) {
  245.             break;
  246.         }
  247.     }
  248.     lens = strlen(buf);
  249.     if (lens) buf[--lens] = '\0';
  250.     if ((pos = getnword(buf, 3)) == NULL ) {
  251.         Console("Missing part name, in included begin line.\r\n");
  252.         part = '?';
  253.     } else {
  254.         part = *pos;
  255. /*
  256.  * Check the part suffix.
  257.  */
  258.         partn++;
  259.         if (part != partn) {
  260.             mism[SUBS1] = part;
  261.             mism[SUBS2] = partn;
  262.             Console(mism);
  263.         }
  264.     }
  265. }
  266.  
  267. /*
  268.  * Output to console, immune against redirection of stdout.
  269.  */
  270. Console(s) register char *s;
  271. {
  272.     while (*s) Bconout(2,*s++);
  273. }
  274.